package org.springblade.tms.module.exceptionrecord.base;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.logging.log4j.util.Strings;
import org.springblade.common.utils.EnumUtils;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.system.user.entity.User;
import org.springblade.system.user.feign.IUserSearchClient;
import org.springblade.tms.global.enums.DemandStatusEnum;
import org.springblade.tms.global.enums.OrderTypeEnum;
import org.springblade.tms.global.enums.WaybillStatusEnum;
import org.springblade.tms.module.common.dto.DeleteDto;
import org.springblade.tms.module.demandorder.entity.TMDemandOrder;
import org.springblade.tms.module.demandorder.service.IDemandOrderService;
import org.springblade.tms.module.exceptionreason.entity.TMExceptionReason;
import org.springblade.tms.module.exceptionreason.service.IExceptionReasonService;
import org.springblade.tms.module.exceptionrecord.dto.ExceptionRecordDTO;
import org.springblade.tms.module.exceptionrecord.entity.TMExceptionRecord;
import org.springblade.tms.module.exceptionrecord.service.IExceptionRecordService;
import org.springblade.tms.module.exceptionrecord.vo.TMExceptionRecordVO;
import org.springblade.tms.module.exceptionrecord.wrapper.ExceptionRecordWrapper;
import org.springblade.tms.module.exceptiontype.entity.TMExceptionType;
import org.springblade.tms.module.exceptiontype.service.IExceptionTypeService;
import org.springblade.tms.module.transportorder.entity.TMTransportOrder;
import org.springblade.tms.module.transportorder.service.ITransportOrderService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @projectName: BladeX
 * @package: org.springblade.tms.module.exceptionrecord.base
 * @className: AbnormalRecordService
 * @author: yr
 * @description: 异常记录服务
 * @date: 2022/3/29 15:24
 */
@Service
@Transactional
public class AbnormalRecordService {
    @Resource
    private IExceptionTypeService exceptionTypeService;
    @Resource
    private IExceptionReasonService exceptionReasonService;
    @Resource
    private IExceptionRecordService exceptionRecordService;
    @Resource
    private IUserSearchClient userClient;
    @Resource
    private IDemandOrderService demandOrderService;
    @Resource
    private ITransportOrderService transportOrderService;

    /**
     * @param :
     * @return R
     * @author yr
     * @description 异常记录列表查询
     * @date 2022/3/29 16:16
     */
    public R list(ExceptionRecordDTO exceptionRecordDTO, Query query) {
        //条件查询
        LambdaQueryWrapper<TMExceptionRecord> lambdaQueryWrapper = Condition.getQueryWrapper(new TMExceptionRecord()).lambda();
        //根据运输单号
        if (Strings.isNotEmpty(exceptionRecordDTO.getShippingNoteNumber())) {
            List<TMTransportOrder> transportOrders = transportOrderService.lambdaQuery()
                    .like(TMTransportOrder::getTransportNo, exceptionRecordDTO.getShippingNoteNumber())
                    .list();
            List<Long> collect = transportOrders.stream().map(TMTransportOrder::getId).collect(Collectors.toList());
            if (collect.isEmpty()) {
                return R.data(new Page<>());
            }
            lambdaQueryWrapper = lambdaQueryWrapper.in(TMExceptionRecord::getParentId, collect);
        }
        //根据异常类型
        if (exceptionRecordDTO.getExceptionType() != null && !exceptionRecordDTO.getExceptionType().isEmpty()) {
            List<Long> exceptionTypeIds = exceptionTypeService.lambdaQuery().like(TMExceptionType::getName, exceptionRecordDTO.getExceptionType()).list()
                    .stream().map(TMExceptionType::getId).collect(Collectors.toList());
            lambdaQueryWrapper = lambdaQueryWrapper.in(TMExceptionRecord::getId, exceptionTypeIds);
        }
        //根据时间
        lambdaQueryWrapper = lambdaQueryWrapper.between(exceptionRecordDTO.getAbnormalTimeStarts() != null,
                TMExceptionRecord::getCreateTime, exceptionRecordDTO.getAbnormalTimeStarts(), exceptionRecordDTO.getAbnormalTimeEnd());
        lambdaQueryWrapper.eq(Strings.isNotEmpty(exceptionRecordDTO.getWaybillStatus()), TMExceptionRecord::getOrderStatus, exceptionRecordDTO.getWaybillStatus());
        //根据需求单号
        if (Strings.isNotEmpty(exceptionRecordDTO.getDemandOrderNumber())) {
            List<TMDemandOrder> tmDemandOrders = demandOrderService.lambdaQuery().like(TMDemandOrder::getDemandOrderNumber, exceptionRecordDTO.getDemandOrderNumber()).list();
            List<Long> demandOrderIds = tmDemandOrders.stream().map(TMDemandOrder::getId).collect(Collectors.toList());
            List<Long> transportOrderIds = transportOrderService.lambdaQuery().in(TMTransportOrder::getDemandId, demandOrderIds).list()
                    .stream().map(TMTransportOrder::getId).collect(Collectors.toList());
            lambdaQueryWrapper = lambdaQueryWrapper.and(tmExceptionRecord -> tmExceptionRecord.in(TMExceptionRecord::getParentId, transportOrderIds)
                    .or().in(TMExceptionRecord::getParentId, demandOrderIds));
        }
        IPage<TMExceptionRecord> page = exceptionRecordService.page(Condition.getPage(query), lambdaQueryWrapper.orderByDesc(TMExceptionRecord::getCreateTime, TMExceptionRecord::getId));
        List<TMExceptionRecord> exceptionRecords = page.getRecords();
        //上传人封装
        List<Long> userIds2 = exceptionRecords.stream().map(TMExceptionRecord::getCreateUser).collect(Collectors.toList());
        IPage<TMExceptionRecordVO> exceptionRecordVOIPage = ExceptionRecordWrapper.build().pageVO(page);
        List<TMExceptionRecordVO> tmExceptionRecordVOS = exceptionRecordVOIPage.getRecords();
        if (!userIds2.isEmpty()) {
            String join2 = StringUtil.join(userIds2, ",");
            R<List<User>> user2 = userClient.listByUser(join2);
            Map<Long, String> userMap2 = user2.getData().stream().collect(Collectors.toMap(User::getId, User::getName));
            tmExceptionRecordVOS.forEach(tmExceptionRecordDTO -> tmExceptionRecordDTO.setOperator(userMap2.get(tmExceptionRecordDTO.getCreateUser())));
        }
        //封装异常类型
        List<Long> exceptionTypeIds = exceptionRecords.stream().map(TMExceptionRecord::getExceptionType).collect(Collectors.toList());
        List<TMExceptionType> tmExceptionTypes = exceptionTypeService.lambdaQuery().in(!exceptionTypeIds.isEmpty(), TMExceptionType::getId, exceptionTypeIds).list();
        Map<Long, String> exceptionTypeMap = tmExceptionTypes.stream().collect(Collectors.toMap(TMExceptionType::getId, TMExceptionType::getName));
        tmExceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setExceptionClass(exceptionTypeMap.get(tmExceptionRecordVO.getExceptionType())));
        //封装异常原因
        List<Long> exceptionReasonList = exceptionRecords.stream().map(TMExceptionRecord::getExceptionTypeDesc).collect(Collectors.toList());
        List<TMExceptionReason> tmExceptionReasons = exceptionReasonService.lambdaQuery().in(!exceptionReasonList.isEmpty(), TMExceptionReason::getId, exceptionReasonList).list();
        Map<Long, String> exceptionReasonMap = tmExceptionReasons.stream().collect(Collectors.toMap(TMExceptionReason::getId, TMExceptionReason::getReasonDesc));
        tmExceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setAbnormal(exceptionReasonMap.get(tmExceptionRecordVO.getExceptionTypeDesc())));
        //封装需求单或运单号
        Map<String, List<TMExceptionRecordVO>> ExceptionRecordMap = tmExceptionRecordVOS.stream().collect(Collectors.groupingBy(TMExceptionRecord::getOrderType));
        List<TMExceptionRecordVO> tmExceptionRecordVOList = new ArrayList<>();
        for (String s : ExceptionRecordMap.keySet()) {
            if (s.equals(OrderTypeEnum.SINGLE_TRANSPORT.value())) {
                List<TMExceptionRecordVO> exceptionRecordVOS = ExceptionRecordMap.get(s);
                List<Long> orderIds = exceptionRecordVOS.stream().map(TMExceptionRecord::getParentId).collect(Collectors.toList());
                List<TMTransportOrder> tmTransportOrders = transportOrderService.lambdaQuery().in(TMTransportOrder::getId, orderIds).list();
                List<Long> demandIds = tmTransportOrders.stream().map(TMTransportOrder::getDemandId).collect(Collectors.toList());
                List<TMDemandOrder> tmDemandOrders = demandOrderService.lambdaQuery().in(TMDemandOrder::getId, demandIds).list();
                Map<Long, List<TMDemandOrder>> map = tmDemandOrders.stream().collect(Collectors.groupingBy(TMDemandOrder::getId));
                Map<Long, Long> demandIdMap = tmTransportOrders.stream().collect(Collectors.toMap(TMTransportOrder::getId, TMTransportOrder::getDemandId));
                Map<Long, String> shippingNoteNumberMap = tmTransportOrders.stream().collect(Collectors.toMap(TMTransportOrder::getId, TMTransportOrder::getTransportNo));
                Map<Long, String> orderTypeMap = tmTransportOrders.stream().collect(Collectors.toMap(TMTransportOrder::getId, TMTransportOrder::getTransportStatus));
                exceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setDemandOrderNumber(map.get(demandIdMap.get(tmExceptionRecordVO.getParentId())).get(0).getDemandOrderNumber()));
                exceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setShippingNoteNumber(shippingNoteNumberMap.get(tmExceptionRecordVO.getParentId())));
                exceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setWaybillStatus(WaybillStatusEnum.getDescriptionByValue(orderTypeMap
                        .get(tmExceptionRecordVO.getParentId()))));
                tmExceptionRecordVOList.addAll(exceptionRecordVOS);
            } else {
                List<TMExceptionRecordVO> exceptionRecordVOS = ExceptionRecordMap.get(s);
                List<Long> orderIds = exceptionRecordVOS.stream().map(TMExceptionRecord::getParentId).collect(Collectors.toList());
                List<TMDemandOrder> tmDemandOrders = demandOrderService.lambdaQuery().in(TMDemandOrder::getId, orderIds).list();
                Map<Long, List<TMDemandOrder>> map = tmDemandOrders.stream().collect(Collectors.groupingBy(TMDemandOrder::getId));
                Map<Long, String> demandOrderTypeMap = tmDemandOrders.stream().collect(Collectors.toMap(TMDemandOrder::getId, TMDemandOrder::getDemandStatus));
                exceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setWaybillStatus((EnumUtils.getEnumByValue(DemandStatusEnum.class, demandOrderTypeMap
                        .get(tmExceptionRecordVO.getParentId())).get().description())));
                exceptionRecordVOS.forEach(tmExceptionRecordVO -> tmExceptionRecordVO.setDemandOrderNumber(map.get(tmExceptionRecordVO.getParentId()).get(0).getDemandOrderNumber()));
                tmExceptionRecordVOList.addAll(exceptionRecordVOS);
            }
        }
        return R.data(exceptionRecordVOIPage);
    }

    /**
     * @param deleteDto:
     * @return R<Boolean>
     * @author yr
     * @description 批量删除异常记录
     * @date 2022/3/29 18:20
     */
    public R<Boolean> delete(DeleteDto deleteDto) {
        boolean deleteLogic = exceptionRecordService.deleteLogic(deleteDto.getIds());
        return R.status(deleteLogic);
    }
}
